#As always, we import everything
import os
import pandas as pd
import json
import folium
import math
%matplotlib inline
import matplotlib.pyplot as plt
from geopy.geocoders import Nominatim
import base64
First, let's get the data and put it in a dataframe.
eu_data = pd.read_table('tsdec450.tsv', na_values=': ')
Now, we can process it to get the id for each country.
eu_data['info'] = eu_data['info'].apply(lambda x: x.split(",")[3])
eu_data
Now we can define a function that returns the color of a country based on its unemployement rate. For this, we need to choose a palette of colors : we used colorbrewer to get one which is color-blind friendly. To get the color for a country, we simply bin all the unemployement_rate into one of the colors.
In this function, we also create a mapping from country id to country name.
#colors_unemployement = ['#fee5d9','#fcbba1','#fc9272','#fb6a4a','#de2d26','#a50f15']
colors_unemployement = ['#fef0d9','#fdd49e','#fdbb84','#fc8d59','#e34a33','#b30000']
min_unemployement_eu = eu_data['2016'].min()
max_unemployement_eu = eu_data['2016'].max()
id_country_mapping = {}
def get_color_eu(country, properties):
global id_country_mapping
id_country_mapping[country] = properties['NAME']
values = eu_data.loc[eu_data['info'] == country, '2016'].values
if len(values) == 0:
return '#000000'
unemployement_rate = values[0]
ratio = (unemployement_rate - min_unemployement_eu) / (max_unemployement_eu - min_unemployement_eu)
index = math.floor(ratio * len(colors_unemployement))
if index == len(colors_unemployement):
index = index - 1
return colors_unemployement[index]
#TODO : Check colors + maybe change intervals
We also define a function that checks if a country is in the dataframe, and if not, we make its overly transparent.
def get_opacity_eu(country):
values = eu_data.loc[eu_data['info'] == country, '2016'].values
return 1 if len(values) > 0 else 0
Now we can create the Europe map, and add the overlay, using the previous functions.
The second map is only used to display the legend. We used to following website to convert the topojson file to gejson https://jeffpaine.github.io/geojson-topojson/
map_eu = folium.Map([51,15], tiles='cartodbpositron', zoom_start=4)
# Color of the country
folium.TopoJson(
open('topojson/europe.topojson.json'),
object_path='objects.europe',
style_function=lambda feature: {
'fillOpacity' : get_opacity_eu(feature['id']), #opacity for the fill color
'opacity' : get_opacity_eu(feature['id']), #opacity for the borders
'fillColor': get_color_eu(feature['id'], feature['properties']),
'color' : 'black',
'weight' : 1
}
).add_to(map_eu)
#
"""map_eu.choropleth(geo_data='topojson/europe.geojson.json',data=eu_data,
columns=['info', '2016'],
key_on='feature.id',
fill_color='OrRd',
#fill_color='RdGy',
fill_opacity=0,
line_opacity=0.0,
legend_name='Percentage of unemployement in country')"""
We used the geopy library to get the position of the center of each country. This position is then used to place a marker with the graph of unemployement.
"""position_mapping = {}
geolocator = Nominatim()
for country_id in eu_data['info']:
if country_id in id_country_mapping:
location = geolocator.geocode(id_country_mapping[country_id])
if (location):
position_mapping[country_id] = [location.latitude,location.longitude]
with open('position_mapping.json', 'w') as outfile:
json.dump(position_mapping, outfile)
with open('id_country_mapping.json', 'w') as outfile:
json.dump(id_country_mapping, outfile)"""
with open('position_mapping.json', 'r') as infile:
position_mapping = json.load(infile)
with open('id_country_mapping.json', 'r') as infile:
id_country_mapping = json.load(infile)
For each country we create a graph and save it.
for index, row in eu_data.iterrows():
global id_country_mapping
if row.values[0] in id_country_mapping:
row_values = row.iloc[1:].astype(float)
plot = row_values.transpose().plot()
plt.ylim(0,30)
plt.xlabel('Year')
plt.ylabel('% of unemployed')
plt.title('Graph of unemployment in ' + id_country_mapping[row.values[0]])
plt.savefig('eu_graphs/graph' + row.values[0] + '.png')
plt.close()
For each country we place a custom marker (a black disk) that displays the graph when clicked.
all_markers = folium.FeatureGroup("Markers")
for country_id in eu_data['info']:
if country_id in position_mapping:
location = position_mapping[country_id]
if location:
encoded = base64.b64encode(open('eu_graphs/graph' + country_id + '.png', 'rb').read()).decode()
html = '<img src="data:image/png;base64,{}" width=450 height=300>'.format
iframe = folium.IFrame(html(encoded), width=470, height=320)
popup = folium.Popup(iframe, max_width=2650)
custom_icon = folium.features.CustomIcon("http://www.i2symbol.com/images/symbols/geometry/black_circle_u25CF_icon_256x256.png", icon_size=(25, 25))
all_markers.add_child(folium.Marker(location, popup=popup, icon=custom_icon))
map_eu.add_child(all_markers)
map_eu
#ch_data_raw = pd.read_csv('data/unemployed_switzerland.csv')
ch_data = pd.read_csv('data/unemployed_switzerland.csv')
"""groups = ch_data_raw[['Year', 'Canton', 'Unemployment Rate']].groupby(['Canton'])
cantons = ch_data_raw['Canton'].unique()
years = ch_data_raw['Year'].unique()
ch_data = pd.DataFrame(index = cantons, columns=years)
for group, data in groups:
ch_data.loc[group] = data['Unemployment Rate'].values
"""
ch_data
colors_unemployement = ['#fef0d9','#fdd49e','#fdbb84','#fc8d59','#e34a33','#b30000']
min_unemployement_ch = ch_data['2017'].min()
max_unemployement_ch = ch_data['2017'].max()
id_canton_mapping = {}
def get_color_ch(canton, properties):
global id_canton_mapping
id_canton_mapping[canton] = properties['name']
values = ch_data.loc[ch_data['Canton'] == canton, '2017'].values
if len(values) == 0:
return '#000000'
unemployement_rate = values[0]
ratio = (unemployement_rate - min_unemployement_ch) / (max_unemployement_ch - min_unemployement_ch)
index = math.floor(ratio * len(colors_unemployement))
if index == len(colors_unemployement):
index = index - 1
return colors_unemployement[index]
map_ch = folium.Map([46.8,8.3], tiles='cartodbpositron', zoom_start=8)
# Color of the country
folium.TopoJson(
open('topojson/ch-cantons.topojson.json'),
object_path='objects.cantons',
style_function=lambda feature: {
'fillOpacity' : 1,#get_opacity_eu(feature['id']), #opacity for the fill color
'opacity' : 1,#get_opacity_eu(feature['id']), #opacity for the borders
'fillColor': get_color_ch(feature['id'], feature['properties']),
'color' : 'black',
'weight' : 1
}
).add_to(map_ch)
"""position_canton_mapping = {}
geolocator = Nominatim()
for canton_id in id_canton_mapping:
location = geolocator.geocode(id_canton_mapping[canton_id])
if (location):
position_canton_mapping[canton_id] = [location.latitude,location.longitude]
with open('position_canton_mapping.json', 'w') as outfile:
json.dump(position_canton_mapping, outfile)
with open('id_canton_mapping.json', 'w') as outfile:
json.dump(id_canton_mapping, outfile)"""
with open('position_canton_mapping.json', 'r') as infile:
position_canton_mapping = json.load(infile)
with open('id_canton_mapping.json', 'r') as infile:
id_canton_mapping = json.load(infile)
for index, row in ch_data.iterrows():
global id_canton_mapping
if row.values[0] in id_canton_mapping:
row_values = row.iloc[1:].astype(float)
plot = row_values.transpose().plot()
plt.ylim(0,30)
plt.xlabel('Year')
plt.ylabel('% of unemployed')
plt.title('Graph of unemployment in ' + id_canton_mapping[row.values[0]])
plt.savefig('ch_graphs/graph' + row.values[0] + '.png')
plt.close()
all_markers = folium.FeatureGroup("Markers")
for canton_id in id_canton_mapping:
location = position_canton_mapping[canton_id]
encoded = base64.b64encode(open('ch_graphs/graph' + canton_id + '.png', 'rb').read()).decode()
html = '<img src="data:image/png;base64,{}" width=450 height=300>'.format
iframe = folium.IFrame(html(encoded), width=470, height=320)
#iframe = folium.IFrame("<p>" + id_canton_mapping[canton_id] + "</p>", width=470, height=320)
popup = folium.Popup(iframe, max_width=2650)
custom_icon = folium.features.CustomIcon("http://www.i2symbol.com/images/symbols/geometry/black_circle_u25CF_icon_256x256.png", icon_size=(25, 25))
all_markers.add_child(folium.Marker(location, popup=popup, icon=custom_icon))
map_ch.add_child(all_markers)
map_ch
ch_data2 = pd.read_csv('data/unemployed_num_switzerland.csv', thousands="'")
ch_data3 = pd.read_csv('data/jobseekers_switzerland.csv', thousands="'")
ch_data4 = pd.read_csv('data/unemployed_foreigner_swiss.csv', thousands="'")
active_pop = ((ch_data2.iloc[:, 1:] * 100) / ch_data.iloc[:, 1:])
ch_jobseeker_rate = (ch_data3.iloc[:, 1:] * 100) / active_pop
ch_jobseeker_rate = pd.concat((ch_data['Canton'], ch_jobseeker_rate), axis=1)
active_pop.to_csv('data/pop_canton.csv')
colors_unemployement = ['#fef0d9','#fdd49e','#fdbb84','#fc8d59','#e34a33','#b30000']
min_jobseeker_ch = ch_jobseeker_rate['2017'].min()
max_jobseeker_ch = ch_jobseeker_rate['2017'].max()
def get_color_ch_j(canton, properties):
values = ch_jobseeker_rate.loc[ch_jobseeker_rate['Canton'] == canton, '2017'].values
if len(values) == 0:
return '#000000'
jobseeker_rate = values[0]
ratio = (jobseeker_rate - min_jobseeker_ch) / (max_jobseeker_ch - min_jobseeker_ch)
index = math.floor(ratio * len(colors_unemployement))
if index == len(colors_unemployement):
index = index - 1
return colors_unemployement[index]
map_ch_j = folium.Map([46.8,8.3], tiles='cartodbpositron', zoom_start=8)
# Color of the country
folium.TopoJson(
open('topojson/ch-cantons.topojson.json'),
object_path='objects.cantons',
style_function=lambda feature: {
'fillOpacity' : 1,#get_opacity_eu(feature['id']), #opacity for the fill color
'opacity' : 1,#get_opacity_eu(feature['id']), #opacity for the borders
'fillColor': get_color_ch_j(feature['id'], feature['properties']),
'color' : 'black',
'weight' : 1
}
).add_to(map_ch_j)
for index, row in ch_jobseeker_rate.iterrows():
global id_canton_mapping
row_values = row.iloc[1:].astype(float)
plot = row_values.transpose().plot()
plt.ylim(0,30)
plt.xlabel('Year')
plt.ylabel('% of unemployed')
plt.title('Graph of unemployment in ' + id_canton_mapping[row.values[0]])
plt.savefig('ch_graphs/graph_j_' + row.values[0] + '.png')
plt.close()
ch_jobseeker_rate
all_markersj = folium.FeatureGroup("Markers")
for canton_id in id_canton_mapping:
location = position_canton_mapping[canton_id]
encoded = base64.b64encode(open('ch_graphs/graph_j_' + canton_id + '.png', 'rb').read()).decode()
html = '<img src="data:image/png;base64,{}" width=450 height=300>'.format
iframe = folium.IFrame(html(encoded), width=470, height=320)
#iframe = folium.IFrame("<p>" + id_canton_mapping[canton_id] + "</p>", width=470, height=320)
popup = folium.Popup(iframe, max_width=2650)
custom_icon = folium.features.CustomIcon("http://www.i2symbol.com/images/symbols/geometry/black_circle_u25CF_icon_256x256.png", icon_size=(25, 25))
all_markersj.add_child(folium.Marker(location, popup=popup, icon=custom_icon))
map_ch_j.add_child(all_markersj)
map_ch_j
ch_data4
ch_foreigner = ch_data4[ch_data4.Nationalité == 'Etrangers']
ch_foreigner.index = range(0,len(ch_foreigner))
ch_foreigner = ch_foreigner.drop('Nationalité', axis=1)
ch_swiss = ch_data4[ch_data4.Nationalité == 'Suisses']
ch_swiss.index = range(0,len(ch_swiss))
ch_swiss = ch_swiss.drop('Nationalité', axis=1)
ch_swiss_rate = (ch_swiss.iloc[:, 1:] * 100) / active_pop
ch_swiss_rate = pd.concat((ch_data['Canton'], ch_swiss_rate), axis=1)
ch_foreigner_rate = (ch_foreigner.iloc[:, 1:] * 100) / active_pop
ch_foreigner_rate = pd.concat((ch_data['Canton'], ch_foreigner_rate), axis=1)
ch_swiss
for index, row in ch_swiss_rate.iterrows():
global id_canton_mapping
row_values = row.iloc[2:].astype(float)
plot = row_values.transpose().plot()
row_values = ch_foreigner_rate.iloc[index][2:].astype(float)
plot = row_values.transpose().plot()
plt.ylim(0,10)
plt.legend(['Swiss', 'Foreigners'])
plt.xlabel('Year')
plt.ylabel('% of unemployed')
plt.title('Graph of unemployment in ' + id_canton_mapping[row.values[0]])
plt.savefig('ch_graphs/graph_s_f_' + row.values[0] + '.png')
plt.close()
for index, row in ch_swiss_rate.iterrows():
global id_canton_mapping
#serie = pd.Series([row.iloc[-1], ch_foreigner_rate.iloc[index][-1]])
row_values = [row.iloc[-1], ch_foreigner_rate.iloc[index][-1]]
plot = plt.bar([0,1], row_values, edgecolor='black',linewidth=10)
plot[0].set_color('b')
plot[0].set_linewidth(30)
plot[1].set_color('orange')
plt.ylim(0,6)
plt.axis('off')
plt.savefig('icon_ch/icon_' + row.values[0] + '.png')
plt.close()
colors_s_f_neg = ['#b2182b','#d6604d','#f4a582','#fddbc7']
colors_s_f_pos = ['#d1e5f0','#92c5de','#4393c3','#2166ac']
diff_ch_for = ch_swiss_rate.drop('Canton', axis=1).subtract(ch_foreigner_rate.drop('Canton', axis=1))
diff_ch_for = pd.concat((ch_data['Canton'], diff_ch_for), axis=1)
min_s_f_ch = diff_ch_for['2017'].min()
max_s_f_ch = diff_ch_for['2017'].max()
def get_color_ch_s_f(canton, properties):
diff_ch_s_f = diff_ch_for.loc[diff_ch_for['Canton'] == canton, '2017'].values
if (diff_ch_s_f < 0):
ratio = (diff_ch_s_f - min_s_f_ch) / (-min_s_f_ch)
colors = colors_s_f_neg
else:
ratio = (diff_ch_s_f) / (max_s_f_ch)
colors = colors_s_f_pos
index = math.floor(ratio * len(colors))
if index == len(colors):
index = index - 1
return colors[index]
map_ch_s_f = folium.Map([46.8,8.3], tiles='cartodbpositron', zoom_start=8)
# Color of the country
folium.TopoJson(
open('topojson/ch-cantons.topojson.json'),
object_path='objects.cantons',
style_function=lambda feature: {
'fillOpacity' : 1,#get_opacity_eu(feature['id']), #opacity for the fill color
'opacity' : 1,#get_opacity_eu(feature['id']), #opacity for the borders
'fillColor': get_color_ch_s_f(feature['id'], feature['properties']),
'color' : 'black',
'weight' : 1
}
).add_to(map_ch_s_f)
all_markers_s_f = folium.FeatureGroup("Markers")
for canton_id in id_canton_mapping:
location = position_canton_mapping[canton_id]
encoded = base64.b64encode(open('ch_graphs/graph_s_f_' + canton_id + '.png', 'rb').read()).decode()
html = '<img src="data:image/png;base64,{}" width=450 height=300>'.format
iframe = folium.IFrame(html(encoded), width=470, height=320)
#iframe = folium.IFrame("<p>" + id_canton_mapping[canton_id] + "</p>", width=470, height=320)
popup = folium.Popup(iframe, max_width=2650)
custom_icon = folium.features.CustomIcon("http://feudal-ambitions.com/ADA/HW3/IconsSF/icon_"+canton_id +".png", icon_size=(30, 60))
all_markers_s_f.add_child(folium.Marker(location, popup=popup, icon=custom_icon))
map_ch_s_f.add_child(all_markers_s_f)
map_ch_s_f